Building your first project

Creating your project

To create a new Uno app, there are two options available to developers. The first is to use Uno.Templates by invoking the dotnet new command, which provides a quick and straightforward way to get started with an Uno project. The second option is to use the Uno Platform Template Wizard, which provides a more guided approach to creating an Uno app.

In the following sections, we will cover both methods for creating a new Uno app, providing step-by-step instructions for each.

For this project, we will be using the unoapp solution template. This template includes two preset configurations, blank and recommended, and a large number of other options that can be used to define the structure of the app to be created by the template.

For this project, we're going to select the blank preset, which only includes the minimum features required for an Uno Platform application. We're also going to select the Material theme and include the Uno Toolkit for the helper functions to switch themes.

By default, the project will be created with XAML and using the MVVM pattern.

dotnet new unoapp -preset blank -tfm net8.0 -presentation mvvm -toolkit true -theme material -theme-service -o SimpleCalculator
Note

After creating the SimpleCalculator application, open the Solution File (Visual Studio) or Solution Folder (Visual Studio Code) and ensure you can build and run the application.

Prepare the Project

Before we continue to the next section, add the Calculator class by adding a new file called Calculator.cs into the SimpleCalculator project. Replace the default Calculator class with the following source code.

Calculator.cs code contents (collapsed for brevity)
using System.Globalization;

namespace SimpleCalculator;

public record Calculator
{
    private string? Number { get; init; }
    private string? Operator { get; init; }
    private double? Number1 { get; init; }
    private double? Number2 { get; init; }
    private bool IsNumber2Percentage { get; init; }
    private double? Result { get; init; }
    private bool HasOperator => !string.IsNullOrEmpty(Operator);
    private bool HasNumber => !string.IsNullOrEmpty(Number);
    private bool HasNumber1 => Number1 != null;

    public string Output => $"{(Result != null ? Result.Value.ToString(CultureInfo.InvariantCulture) : HasNumber ? Number : "0")}";
    public string Equation => $"{Number1?.ToString(CultureInfo.InvariantCulture)} {Operator} {Number2?.ToString(CultureInfo.InvariantCulture)}{(IsNumber2Percentage ? "%" : string.Empty)}{(Result != null ? $" =" : string.Empty)}";

    public Calculator Input(string key)
    {
        var calculator = RestartOrClear(key);
        return key switch
        {
            "÷" or "×" or "+" or "−" => OperatorKey(calculator, key),
            "back" => BackKey(calculator),
            "." => DotKey(calculator),
            "0" when !calculator.HasNumber => calculator,
            "C" => new(),
            "=" => EqualsKey(calculator),
            "%" => PercentageKey(calculator),
            "±" => PlusMinusKey(calculator),

            _ => calculator with { Number = calculator.Number + key }
        };
    }

    private Calculator RestartOrClear(string key)
    {
        if (Result != null)
        {
            if (key == "÷" || key == "×" || key == "+" || key == "−")
            {
                return this with
                {
                    Number1 = Result,
                    Result = null,
                    Number2 = null,
                    Number = null,
                    Operator = key,
                    IsNumber2Percentage = false
                };
            }
            else
            {
                return new();
            }
        }

        return this;
    }

    private static Calculator BackKey(Calculator calculator)
    {
        if (calculator.HasNumber)
        {
            calculator = calculator with
            {
                Number = calculator.Number?.Substring(0, calculator.Number.Length - 1)
            };
        }

        return calculator;
    }

    private static Calculator DotKey(Calculator calculator)
    {
        if (calculator.HasNumber)
        {
            if (calculator.Number?.Contains(".") == false)
            {
                calculator = calculator with
                {
                    Number = calculator.Number + "."
                };
            }
        }
        else
        {
            calculator = calculator with
            {
                Number = "0."
            };
        }

        return calculator;
    }

    private static Calculator EqualsKey(Calculator calculator)
    {
        if (calculator.HasOperator && calculator.HasNumber1)
        {
            double? number2 = calculator.HasNumber ? GetNumber(calculator.Number) : 0.0;

            double result = calculator.Operator switch
            {
                "÷" => calculator.Number1!.Value / number2!.Value,
                "×" => calculator.Number1!.Value * number2!.Value,
                "+" => calculator.Number1!.Value + number2!.Value,
                "−" => calculator.Number1!.Value - number2!.Value,
                _ => throw new InvalidOperationException()
            };

            calculator = calculator with
            {
                Number2 = number2,
                Result = result
            };
        }

        return calculator;
    }

    private static Calculator PercentageKey(Calculator calculator)
    {
        if (calculator.HasOperator && calculator.HasNumber1)
        {
            double? number2 = calculator.HasNumber ? GetNumber(calculator.Number) : 0.0;

            double result = calculator.Operator switch
            {
                "÷" => calculator.Number1!.Value / (number2!.Value / 100) * calculator.Number1!.Value,
                "×" => calculator.Number1!.Value * (number2!.Value / 100) * calculator.Number1!.Value,
                "+" => calculator.Number1!.Value + (number2!.Value / 100) * calculator.Number1!.Value,
                "−" => calculator.Number1!.Value - (number2!.Value / 100) * calculator.Number1!.Value,
                _ => throw new InvalidOperationException()
            };

            calculator = calculator with
            {
                Number2 = number2,
                Result = result,
                IsNumber2Percentage = true
            };
        }

        return calculator;
    }

    private static Calculator PlusMinusKey(Calculator calculator)
    {
        if (calculator.HasNumber)
        {
            calculator = calculator with { Number = calculator.Number?.StartsWith("-") == true ? calculator.Number?.Substring(1) : "-" + calculator.Number };
        }
        return calculator;
    }

    private static Calculator OperatorKey(Calculator calculator, string key)
    {
        if(calculator.HasNumber)
        {
            if(calculator.HasOperator && calculator.HasNumber1) 
            {
                calculator = EqualsKey(calculator);

                calculator = calculator with
                {
                    Operator = key,
                    Number1 = calculator.Result,
                    Number = null,
                    Number2 = null,
                    Result = null
                };
            }
            else if (!calculator.HasOperator)
            {
                calculator = calculator with
                {
                    Operator = key,
                    Number1 = GetNumber(calculator.Number),
                    Number = null
                };
            }
        }
        else if (calculator.HasOperator && calculator.HasNumber1)
        {
            calculator = calculator with
            {
                Operator = key
            };
        }

        return calculator;
    }

    private static double? GetNumber(string? number)
        => Convert.ToDouble(number, CultureInfo.InvariantCulture);
}

Next Steps

Next, we'll add the design to our Simple Calculator. You can choose to bring in the UI from the Uno Figma Plugin and import it, or you can directly add the code to the project without exporting it.

Previous | Import UI from Figma or Creating the Layout